<?php


namespace BeReborn\Annotation;

use BeReborn\Base\Component;
use Exception;
use ReflectionException;

/**
 * Class Annotation
 * @package BeReborn\Annotation
 */
class Annotation extends Component
{

	public $_Scan_directory = [];

	public $namespace = '';

	public $prefix = '';

	public $path = '';

	/**
	 * @throws ReflectionException
	 */
	public function scanningBatch()
	{
		if (!is_array($this->path)) {
			return;
		}

		foreach ($this->path as $item) {
			$this->scanningController($item);
		}
	}

	/**
	 * @param string $path
	 * @throws ReflectionException
	 */
	public function scanningController($path = '')
	{
		if (empty($path)) {
			$path = rtrim($this->path, '/');
		}
		foreach (glob($path . '/*') as $file) {
			if (is_dir($file)) {
				$this->scanningController($path);
			}

			$explode = explode('/', $file);

			$class = str_replace('.php', '', end($explode));

			$reflect = new \ReflectionClass($this->namespace . $class);

			$methods = $reflect->getMethods(\ReflectionMethod::IS_PUBLIC);
			if (empty($methods) || !$reflect->isInstantiable()) {
				continue;
			}

			$controller = $reflect->newInstance();
			foreach ($methods as $function) {
				$comment = $function->getDocComment();

				$methodName = $function->getName();

				preg_match('/@Event\((.*)?\)/', $comment, $events);
				if (!isset($events[1])) {
					continue;
				}

				$event = $events[1];
				if ($event === 'message') {
					preg_match('/@Message\((.*)?\)/', $comment, $message);
					if (isset($message[1])) {
						continue;
					}
					$_key = 'WEBSOCKET:MESSAGE:' . $message[1];
				} else {
					$_key = 'WEBSOCKET:EVENT:' . $event;
				}
				$this->_Scan_directory[$_key] = [$controller, $methodName];
			}
		}
	}


	/**
	 * @param $path
	 * @param ...$param
	 * @return bool|mixed
	 */
	public function runWith($path, $param)
	{
		if (!$this->has($path)) {
			return null;
		}
		return call_user_func($this->_Scan_directory[$path], ...$param);
	}


	/**
	 * @param $path
	 * @return bool|mixed
	 */
	public function has($path)
	{
		return isset($this->_Scan_directory[$path]);
	}

}
